package com.atjava.nebula.core.dao.ibatis;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.atjava.nebula.core.annotation.Column;
import com.atjava.nebula.core.exception.baseExp.SystemException;
import com.atjava.nebula.core.util.func.StringUtil;


/**用于设置动态查询条件的类，可支持排序
 * @author kyo
 *
 */
public class Condition {
    protected List<String> criteriaWithoutValue;

    protected List<Map<String, Object>> criteriaWithSingleValue;

    protected List<Map<String, Object>> criteriaWithListValue;

    protected List<Map<String, Object>> criteriaWithBetweenValue;
    
    protected List<String> orderByClause;
    
    protected String connection="and";//多个条件之间的关系 and 或者 or 默认为and

    public Condition() {
        criteriaWithoutValue = new ArrayList<String>();
        criteriaWithSingleValue = new ArrayList<Map<String, Object>>();
        criteriaWithListValue = new ArrayList<Map<String, Object>>();
        criteriaWithBetweenValue = new ArrayList<Map<String, Object>>();
        orderByClause = new ArrayList<String>();
    }

    /**加入Condition对象的条件
     * @param cond Condition对象
     */
    public void AddCondition(Condition cond)
    {
    	criteriaWithoutValue.addAll(cond.getCriteriaWithoutValue());
    	criteriaWithSingleValue.addAll(cond.getCriteriaWithSingleValue());
    	criteriaWithListValue.addAll(cond.getCriteriaWithListValue());
    	criteriaWithBetweenValue.addAll(cond.getCriteriaWithBetweenValue());
    	orderByClause.addAll(cond.orderByClause);
    }
    /**传入一个表对象，并把对象的属性值自动转换为查询条件
     * @param <T>
     * @param obj 表对象
     */
    public <T>Condition(T obj) {
        this();
        parseModel2Cond(obj);
    }    
    
	/**把实体对象转换为Condition查询条件
	 * @param object 要转换的实体对象
	 */
    protected void parseModel2Cond(Object object) throws SystemException {
				
     		 
		//Field[] fields = object.getClass().getFields();	
		Method[] methods=object.getClass().getMethods();
		
		for(Method m:methods){
			String fName=null;
			Object valObj=null;
			if((!m.getName().startsWith("get") 
					&& !m.getName().startsWith("is") )
					|| m.getName().equals("getClass"))
				continue;
			Column column = m.getAnnotation(Column.class);
			
			if(column == null){
				if(m.getName().startsWith("get"))
					fName=m.getName().substring(3);
				else if(m.getName().startsWith("is"))
					fName=m.getName().substring(2);
				fName=StringUtil.toUnderlineName(fName);
			}else{
				if(column.isField()){
					fName=column.name();
				}
				else
					continue;
			}
			
			try {
				valObj = m.invoke(object);
			} catch (Exception e) {
				throw new SystemException(e, "反射机制，调用invoke(object)失败") ;
			} 
			if(valObj!=null)
				this.addCriterion(fName, "=", valObj);			
		}
		
	}    
    /**设置数据排序，该方法会覆盖原有设置的排序
     * @param property 要排序的字段名
     * @param mode 排序的方向 1－正序 2－倒序
     * @deprecated 这是一个过期的方法，请用setOrder替换
     */
    public void setOrderBy(String property,int mode)
    {
    	orderByClause.clear();
    	if(mode==1)
    		orderByClause.add(Order.asc(property).toString());
    	else if(mode==2)
    		orderByClause.add(Order.desc(property).toString());

    }
    
    /**设置数据排序，该方法会覆盖原有设置的排序
     * @param order 
     */
    public void setOrder(Order order){
    	orderByClause.clear();
    	orderByClause.add(order.toString()); 	
    }
    
    /**
     * 增加排序字段
     * @param property 要排序的字段名
     * @param mode 排序的方向 1－正序 2－倒序
     * @deprecated 这是一个过期的方法，请用addOrder替换
     */
    public void addOrderBy(String property , int mode)
    {
    	if(mode==1)
    		orderByClause.add(Order.asc(property).toString());
    	else if(mode==2)
    		orderByClause.add(Order.desc(property).toString());  	
    }
    
    /**增加排序字段，该方法在原有设置的排序上新增排序字段
     * @param order
     */
    public void addOrder(Order order)
    {
    	orderByClause.add(order.toString());    	
    }    
    /**清除排序设置
     * 
     */
    public void clearOrderBy(){
    	orderByClause.clear();
    }
    /**清除查询条件
     * 
     */
    public void clearCriterion(){
        criteriaWithoutValue.clear();
        criteriaWithSingleValue.clear();
        criteriaWithListValue.clear();
        criteriaWithBetweenValue.clear();
    }

//	public void addCond(String condStr,Object value)
//	{
//		Map<String,Object> map=new HashMap<String,Object>();
//		map.put("condition", condStr);
//		map.put("value", value);
//		criteriaWithSingleValue.add(map);
//	}

    public boolean isValid() {
        return criteriaWithoutValue.size() > 0
            || criteriaWithSingleValue.size() > 0
            || criteriaWithListValue.size() > 0
            || criteriaWithBetweenValue.size() > 0;
    }

    public List<String> getCriteriaWithoutValue() {
        return criteriaWithoutValue;
    }

    public List<Map<String, Object>> getCriteriaWithSingleValue() {
        return criteriaWithSingleValue;
    }

    public List<Map<String, Object>> getCriteriaWithListValue() {
        return criteriaWithListValue;
    }

    public List<Map<String, Object>> getCriteriaWithBetweenValue() {
        return criteriaWithBetweenValue;
    }
    
    /**增加是否为NULL的查询
     * @param property 字段名
     */
    public void addIsNULL(String property)
    {
    	addCriterion(property+" IS NULL");
    }
    /**增加是否不为NULL的查询
     * @param property 字段名
     */    
    public void addIsNotNULL(String property)
    {
    	addCriterion(property+" IS Not NULL");
    }    

    /**增加自定义的查询条件
     * @param condition 查询条件字符串，如 id=1 或者 name like '%张%'
     */
    public void addCriterion(String condition) throws SystemException{
        if (condition == null) {
            throw new SystemException("查询条件不能为空");
        }
        criteriaWithoutValue.add(condition);
    }

    /**增加查询条件
     * @param property 字段名
     * @param condition 条件，如：= 、> 、< 、等
     * @param value 所要查询的值
     */
    public void addCriterion(String property , String condition, Object value) throws SystemException{
        if (value == null) {
            throw new SystemException("对字段 [" + property + "] 的查询条件，值(value)不能为空");
        }
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("condition", property+" "+condition);
        map.put("value", value);
        criteriaWithSingleValue.add(map);
    }

    /**增加对一组值的查询，即是In方式的查询
     * @param property 字段名
     * @param values 包含值的List
     */
    public void addCriterion(String property ,  List<? extends Object> values) throws SystemException{
        if (values == null || values.size() == 0) {
            throw new SystemException("对字段 [" + property + "] 的查询条件，值(value)List不能为空");
        }
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("condition", property);
        map.put("values", values);
        criteriaWithListValue.add(map);
    }
    
    /**增加对一组值的查询，即是In方式的查询
     * @param property 字段名
     * @param values 包含值的List
     */
    public void addCriterion(String property ,  Object [] values) throws SystemException{
        if (values == null || values.length == 0) {
            throw new SystemException("对字段 [" + property + "] 的查询条件，值(value)List不能为空");
        }
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("condition", property);
        map.put("values", values);
        criteriaWithListValue.add(map);
    }

    /**增加两个值之间的查询，即是Between方式的查询
     * @param property 字段名
     * @param value1 值1
     * @param value2 值2
     */
    public void addCriterion(String property ,  Object value1, Object value2) throws SystemException{
        if (value1 == null || value2 == null) {
            throw new SystemException("Between values for " + property + " cannot be null");
        }
        List<Object> list = new ArrayList<Object>();
        list.add(value1);
        list.add(value2);
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("condition", property);
        map.put("values", list);
        criteriaWithBetweenValue.add(map);
    }

	public String getOrderByClause() {
		StringBuffer order=new StringBuffer();
		for(int i=0 ;i<orderByClause.size() ;i++){
			order.append( orderByClause.get(i) );
			if(i+1 != orderByClause.size())
				order.append(',');
		}
		if(order.length()>0)
			return order.toString();
		else
			return null;
			
	}

	/**获得当前多个条件间的关系 and 或者 or
	 * @return 
	 */
	public String getConnection() {
		return connection;
	}
	
	/**设置条件间的关系为and
	 * 
	 */
	public void setConnection2And()
	{
		connection="and";
	}
	
	/**设置条件间的关系为or
	 * 
	 */	
	public void setConnection2Or(){
		connection = "or";
	}


	

}
